package cn.edu.zut.soft.graduate.userCenter.bo;

import cn.edu.zut.soft.basic.core.model.bo.CommonResult;
import cn.edu.zut.soft.basic.core.model.dao.Criteria;
import cn.edu.zut.soft.basic.core.model.dao.Example;
import cn.edu.zut.soft.basic.core.util.MDUtil;
import cn.edu.zut.soft.graduate.base.bo.BasicBOImpl;
import cn.edu.zut.soft.graduate.base.cache.CachePool;
import cn.edu.zut.soft.graduate.base.dao.BasicDAO;
import cn.edu.zut.soft.graduate.base.former.InfoIdentityTransformer;
import cn.edu.zut.soft.graduate.base.predicate.InfoKeyPredicate;
import cn.edu.zut.soft.graduate.base.utils.Comparator.InfoComparator;
import cn.edu.zut.soft.graduate.base.utils.InfoUtils;
import cn.edu.zut.soft.graduate.base.utils.Utils;
import cn.edu.zut.soft.graduate.core.constant.*;
import cn.edu.zut.soft.graduate.core.constant.config.IKEY;
import cn.edu.zut.soft.graduate.core.constant.config.TopicPhase;
import cn.edu.zut.soft.graduate.core.constant.config.TopicPhaseAble;
import cn.edu.zut.soft.graduate.core.design.AdminInfoStrategy;
import cn.edu.zut.soft.graduate.core.design.BasicInfoStrategy;
import cn.edu.zut.soft.graduate.core.design.InfoStrategy;
import cn.edu.zut.soft.graduate.core.model.Impl.*;
import cn.edu.zut.soft.graduate.core.model.view.TeacherGroupVO;
import cn.edu.zut.soft.graduate.core.query.IdentityQuery;
import cn.edu.zut.soft.graduate.core.query.InfoQuery;
import cn.edu.zut.soft.graduate.core.query.IssueQuery;
import cn.edu.zut.soft.graduate.core.vo.*;
import cn.edu.zut.soft.graduate.gradesCenter.dao.GradesDAO;
import cn.edu.zut.soft.graduate.groupCenter.bo.GroupBO;
import cn.edu.zut.soft.graduate.groupCenter.bo.TeacherGroupBO;
import cn.edu.zut.soft.graduate.topicCenter.bo.IssueBO;
import cn.edu.zut.soft.graduate.userCenter.dao.IdentityDAO;
import cn.edu.zut.soft.graduate.userCenter.dao.InfoDAO;
import cn.edu.zut.soft.graduate.userCenter.handler.QueryHandler;
import cn.edu.zut.soft.graduate.userCenter.opjo.Invite;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Transformer;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.util.*;

/**
 * Created by chuchuang on 16/10/22.
 */
@Repository
public class IdentityBOImpl extends BasicBOImpl<Identity, IdentityQuery> implements IdentityBO {

    @Resource
    private IdentityDAO<Identity> identityDAO;

    @Resource
    private InfoBO infoBO;

    @Resource
    private InfoDAO<Info> infoDAO;

    @Resource
    private GroupBO groupBO;

    @Resource
    private TeacherGroupBO teacherGroupBO;

    @Resource
    private IssueBO issueBO;

    @Resource
    private InfoIdentityTransformer infoIdentityTransformer;

    @Resource
    private GradesDAO gradesDAO;

    @Override
    protected BasicDAO<Integer, Identity> getDAO() {
        return identityDAO;
    }


    @Override
    protected List<Criteria> Query(final IdentityQuery identityQuery) {
        Criteria criteria = getCriteria(identityQuery);
        return Collections.singletonList(criteria);
    }

    @Override
    public LoginVO identification(String identity, String pwd) {
        //验证用户属于哪种登录用户,使用正则验证
        LoginMode loginMode = LoginMode.getLoginMode(identity);
        Assert.notNull(loginMode, "账号不符合标准");
        Criteria criteria = new Criteria();
        criteria.andEqualTo(loginMode.getTag(), identity);
        criteria.andEqualTo("pwd", MDUtil.MD5(pwd));
        criteria.andEqualTo("del", 0);
        Example example = new Example();
        example.or(criteria);
        List<Identity> list = getDAO().selectByExample(example);
        Assert.notEmpty(list, "账号或密码错误");
        Assert.isTrue(list.size() == 1, "数据出现错误,请联系管理员");
        LoginVO loginVO = new LoginVO();
        loginVO.setLoginMode(loginMode);
        return getLoginVO(loginVO, list.get(0));
    }

    private LoginVO getLoginVO(LoginVO loginVO, Identity identity) {
        if (identity.getRole() == Role.tea) {
            boolean expert = infoBO.getExpertById(identity.getId());
            loginVO.setExpert(expert);
        }
        loginVO.setId(identity.getId());
        loginVO.setName(identity.getName());
        loginVO.setRole(identity.getRole().name());
        loginVO.setInfoList(getIdentityInitInfo(identity));
        loginVO.setPhone(identity.getPhone());
        return loginVO;
    }

    private List<Info> getIdentityInitInfo(Identity identity) {
        List<InfoStrategy> infoStrategyList = new ArrayList<>();
//        infoStrategyList.add(new BasicInfoStrategy(InfoType.Group,IKEY.GroupLeader,""));
        if (Role.stu == identity.getRole()) {
            getInfoStrategyByStu(infoStrategyList);
        } else if (Role.tea == identity.getRole()) {
            getInfoStrategyByTea(infoStrategyList);
        } else {
            throw new IllegalArgumentException("用户身份错误");
        }
        return infoBO.queryByUserInfoStrategy(identity.getId(), infoStrategyList);
    }

    /**
     * 检索与保存的处理结构不一样,保存需要父类结构
     *
     * @param id
     * @return
     */
    @Override
    public UserDescVO userPersonal(final Integer id) {
        final Identity identity = this.get(id);
        UserDescVO userDescVO = new UserDescVO();
        userDescVO.setIdentity(identity);
        userDescVO.setInfoList(infoBO.queryByUser(id));
        return userDescVO;
    }

    @Override
    public List<UserDescVO> userPersonal(IdentityQuery identityQuery, List<InfoStrategy> infoStrategyList) {
        Example example = new Example(identityQuery);
        Criteria criteria = getCriteria(identityQuery);
        example.or(criteria);
        List<Identity> identityList = identityDAO.selectByExample(example);
        if (identityList.isEmpty()) {
            UserDescVO userDescVO;
            List<UserDescVO> userDescVOList = new ArrayList<>();
            for (Identity identity : identityList) {
                userDescVO = new UserDescVO();
                userDescVO.setIdentity(identity);
                userDescVOList.add(userDescVO);
            }
            return userDescVOList;
        }
        Long count = (long) identityDAO.countByExample(example.cleanPage());
        List<Integer> ids = new ArrayList<>(identityList.size());
        for (Identity identity : identityList) {
            ids.add(identity.getId());
        }
        List<Info> infoList = Collections.emptyList();

        if (!infoStrategyList.isEmpty()) {
            Set<InfoTypeAble> infoTypeSet = new HashSet<>(infoStrategyList.size());
            Set<String> keySet = new HashSet<>(infoStrategyList.size());
            for (InfoStrategy infoStrategy : infoStrategyList) {
                infoTypeSet.add(infoStrategy.getType());
                keySet.add(infoStrategy.getKey());
            }
            Example infoExample = new Example().cleanPage();
            infoExample.createCriteria().andIn("identity_id", ids)
                    .andIn("type", Arrays.asList(infoTypeSet.toArray()))
                    .andIn("`key`", Arrays.asList(keySet.toArray())).andEqualTo("del", del);
            infoList = infoDAO.selectByExample(infoExample);
        }
        List<UserDescVO> userDescVOList = new ArrayList<>();
        UserDescVO userDescVO;
        for (Identity identity : identityList) {
            userDescVO = new UserDescVO();
            userDescVO.setIdentity(identity);
            for (Info info : infoList) {
                if (identity.getId().equals(info.getIdentityId())) {
                    userDescVO.getInfoList().add(info);
                }
            }
            userDescVOList.add(userDescVO);
        }
        identityQuery.setCount(count);
        return userDescVOList;
    }

    @Override
    public List<UserDescVO> userPersonal(IdentityQuery identityQuery) {
        List<InfoStrategy> infoStrategyList = new ArrayList<>();
        getInfoStrategyByStu(infoStrategyList);
        return userPersonal(identityQuery, infoStrategyList);
    }

    private Criteria getCriteria(IdentityQuery identityQuery) {
        Criteria criteria = new Criteria();
        if (StringUtils.isNotBlank(identityQuery.getEmail())) {
            criteria.andEqualTo("email", identityQuery.getEmail());
        }
        if (StringUtils.isNotBlank(identityQuery.getNoId())) {
            criteria.andEqualTo("noid", identityQuery.getNoId());
        }
        if (StringUtils.isNotBlank(identityQuery.getPhone())) {
            criteria.andEqualTo("phone", identityQuery.getPhone());
        }
        if (null != identityQuery.getRole()) {
            criteria.andEqualTo("role", identityQuery.getRole().name());
        }
        if (null != identityQuery.getSex()) {
            criteria.andEqualTo("sex", identityQuery.getSex());
        }
        //ids
        if (CollectionUtils.isNotEmpty(identityQuery.getIds())) {
            criteria.andIn("id", identityQuery.getIds());
        }
        //notIds
        if (CollectionUtils.isNotEmpty(identityQuery.getNotIds())) {
            criteria.andNotIn("id", identityQuery.getNotIds());
        }
        if (null != identityQuery.getDel()) {
            criteria.andEqualTo("del", identityQuery.getDel());
        } else {
            criteria.andEqualTo("del", IKEY.ZERO);
        }
        if (StringUtils.isNotBlank(identityQuery.getName())) {
            criteria.andLike("name", identityQuery.getName() + "%");
        }
        return criteria;
    }

    @Override
    @Transactional
    public Identity resetPwd(Integer id, String operator) {
        Identity identity = get(id);
        //修改密码为手机号学生为学号
        if (identity.getRole() == Role.tea) {
            identity.setPwd(MDUtil.MD5(identity.getPhone()));
        } else {
            identity.setPwd(MDUtil.MD5(identity.getNoId()));
        }
        identity.setUpdateAuthor(operator);
        Example example = new Example();
        example.createCriteria().andEqualTo("id", id).andEqualTo("del", 0);
        getDAO().updateByExampleSelective(identity, example);
        return identity;
    }

    @Override
    @Transactional
    public CommonResult<Identity> alterPwd(final ChangePwdVO changePwdVO, String operator) {
        Example example = new Example();
        example.createCriteria().andEqualTo("id", changePwdVO.getId()).andEqualTo("pwd", MDUtil.MD5(changePwdVO.getOld()));
        List<Identity> identityList = getDAO().selectByExample(example);
        if (identityList.isEmpty()) {
            return CommonResult.errorReturn("旧密码错误,请重新输入");
        }
        if (identityList.size() > 1) {
            logger.error("data is error , data = " + identityList);
            return CommonResult.errorReturn("数据出现错误,请联系管理员");
        }
        Identity identity = new Identity();
        identity.setPwd(MDUtil.MD5(changePwdVO.getNow()));
        //设定修改者
        identity.setUpdateAuthor(operator);
        example = new Example();
        example.createCriteria().andEqualTo("id", changePwdVO.getId()).andEqualTo("del", 0);
        //修改数据
        // FIXME: 16/10/22 加密设定
        identityList.get(0).setPwd(changePwdVO.getNow());
        Assert.isTrue(getDAO().updateByExampleSelective(identity, example) > 0, "修改密码失败");
        return CommonResult.successReturn(identityList.get(0));
    }


    @Override
    @Transactional
    public Witness awardWitness(Integer id, InfoStrategy infoStrategy, String operator) {
        final Identity identity = get(id);
        Assert.notNull(identity, "当前用户不存在");
        infoBO.save(infoStrategy, id, operator);
        return new Witness(identity.getId(), identity.getName());
    }

    @Override
    public CommonResult<List<Integer>> notWitnessTea(List<Witness> Witnes) {
        List<Integer> result = new ArrayList<>();
        if (CollectionUtils.isEmpty(Witnes)) {
            final List<Identity> ident = getDAO().selectByExample(new Example() {
                {

                    createCriteria().andEqualTo("role", "tea");
                }
            });
            for (Identity i : ident) {
                result.add(i.getId());
            }
            return CommonResult.successReturn(result);
        }
        final List<Integer> witnesId = new ArrayList<>();
        for (Witness w : Witnes) {
            witnesId.add(w.getId());
        }
        final List<Identity> ident = getDAO().selectByExample(new Example() {
            {

                createCriteria().andEqualTo("role", "tea").andNotIn("id", witnesId);
            }
        });
        for (Identity i : ident) {
            result.add(i.getId());
        }
        return CommonResult.successReturn(result);
    }

    @Override
    public List<UserDescVO> findGroupMember(LoginVO loginVO, Integer groupId) {
        Assert.notNull(loginVO);
        Assert.notNull(groupId);
        List<Info> infoList = infoBO.queryByInfoStrategy(Collections.<InfoStrategy>singletonList(new BasicInfoStrategy(InfoType.Group, IKEY.GROUP, "" + groupId)));
        Assert.notEmpty(infoList, "小组不存在成员");
        List<Integer> ids = new ArrayList<>();
        CollectionUtils.collect(infoList, new Transformer() {
            @Override
            public Object transform(Object o) {
                return ((Info) o).getIdentityId();
            }
        }, ids);
        Group group = groupBO.get(groupId);
        Assert.notNull(group, "小组不存在 id = " + groupId);
        Assert.notEmpty(ids);
        IdentityQuery identityQuery = new IdentityQuery();
        identityQuery.setIds(ids);
        return userPersonal(identityQuery, findGroupMember(group.getRole()));
    }

    @Override
    public List<UserDescVO> findReverseGroupMember(LoginVO loginVO, Integer groupId, boolean reverse) {
        //判断是否反转
        if (reverse) {
            //检测是否是教师小组
            TeacherGroupVO teacherGroupVO = teacherGroupBO.get(groupId);
            if (teacherGroupVO != null) {
                //没有对接，返回空集合
                if (teacherGroupVO.getParallelism() == null) {
                    return Collections.emptyList();
                }
                //对接成功,反转小组id
                groupId = teacherGroupVO.getParallelism().getId();
            }
        }
        return findGroupMember(loginVO, groupId);
    }

    private List<InfoStrategy> findGroupMember(Role role) {
        List<InfoStrategy> infoStrategyList = new ArrayList<>();
        if (Role.tea == role) {
            infoStrategyList = Arrays.<InfoStrategy>asList(
                    new BasicInfoStrategy(InfoType.Group, IKEY.GROUP, ""),
                    new BasicInfoStrategy(InfoType.Group, IKEY.GroupLeader, ""),
                    new BasicInfoStrategy(InfoType.Group, IKEY.GroupSEC, ""),
                    new BasicInfoStrategy(InfoType.Basic, IKEY.PROFESSIONALLEVER, "")
            );
        }
        if (Role.stu == role) {
            infoStrategyList = Arrays.<InfoStrategy>asList(
                    new BasicInfoStrategy(InfoType.Group, IKEY.GROUP, ""),
                    new BasicInfoStrategy(InfoType.Basic, IKEY.CLAZZ, ""),
                    new BasicInfoStrategy(InfoType.TOPIC, IKEY.TopicName, ""),
                    new BasicInfoStrategy(InfoType.TOPIC, IKEY.TopicId, ""),
                    new BasicInfoStrategy(InfoType.TOPIC, IKEY.ChildTopicId, ""),
                    new BasicInfoStrategy(InfoType.TOPIC, IKEY.ChildTopicName, ""));
        }
        return infoStrategyList;
    }


    @Override
    public CommonResult<Identity> save(Identity identity, String operator) {
        if (null == identity.getSex()) {
            identity.setSex(0);
        }
        identity.setPwd(MDUtil.MD5(identity.getPwd()));
        Example example = new Example();
        example.createCriteria().andEqualTo("noid", identity.getNoId());
        if (identity.getPhone() != null) {
            example.or().andEqualTo("phone", identity.getPhone());
        }
        if (identity.getEmail() != null) {
            example.or().andEqualTo("email", identity.getEmail());
        }
        List<Identity> identityList = getDAO().selectByExample(example);
        if (!identityList.isEmpty()) {
            return CommonResult.errorReturn("账号或手机号或邮箱重复,请重新输入或联系管理员");
        }
        return super.save(identity, operator);
    }

    private void getInfoStrategyByStu(Collection<InfoStrategy> collection) {
        collection.addAll(IKEY.StuInfoAll);
    }

    private void getInfoStrategyByTea(Collection<InfoStrategy> collection) {
        collection.add(AdminInfoStrategy.admin);
        collection.add(new BasicInfoStrategy(InfoType.Group, IKEY.GROUP, ""));
        collection.add(new BasicInfoStrategy(InfoType.Group, IKEY.GroupSEC, ""));
        collection.add(new BasicInfoStrategy(InfoType.Group, IKEY.GroupLeader, ""));
    }

    @Override
    public List<UserDescVO> findCanInvitationUser(Invite invite, QueryHandler queryHandler) {
        Assert.notNull(invite);
        //修改小组负责人
//        if (Role.Runner.user == invite.getRunner()) {
//            Assert.notNull(invite.getUser(), "user is null");
//            Assert.notNull(invite.getUser().getId(), "user.is is null");
//            invite.setOwner(invite.getUser().getId());
//        }
        //获取主要负责人信息
//        Assert.notNull(invite.getOwner(), "owner is error");
//        Identity identity = get(invite.getOwner());
//        Assert.notNull(identity, "用户不存在:id = " + invite.getOwner());
//        Assert.isTrue(Role.stu == identity.getRole(), "非学生无法检索");
        Assert.notNull(invite.getIdentityQuery());
        queryHandler.createQuery(invite.getIdentityQuery());
        //优化
        if (CollectionUtils.isEmpty(invite.getIdentityQuery().getIds())) {
            return Collections.emptyList();
        }
        List<InfoStrategy> infoStrategyList = null;
        if (invite.getIdentityQuery().getRole() == Role.stu) {
            infoStrategyList = Collections.<InfoStrategy>singletonList(new BasicInfoStrategy(InfoType.Basic, IKEY.CLAZZ, ""));
        } else {
            infoStrategyList = Collections.<InfoStrategy>singletonList(new BasicInfoStrategy(InfoType.Basic, IKEY.PROFESSIONALLEVER, ""));
        }
        Assert.notEmpty(infoStrategyList);
        return userPersonal(invite.getIdentityQuery(), infoStrategyList);
    }

    /**
     * 根据infoquery 检索出符合条件的成员
     *
     * @param infoQuery
     * @return
     */
    @Override
    public CommonResult<List<UserDescVO>> findByInfo(InfoQuery infoQuery) {
        Assert.notNull(infoQuery);
        CommonResult<List<Info>> result = infoBO.findByQuery(infoQuery);
        List<Info> infoList = result.getData();
        if (CollectionUtils.isEmpty(infoList)) {
            return CommonResult.successReturn(Collections.<UserDescVO>emptyList());
        }
        Set<Integer> ids = new HashSet<>(infoList.size());
        CollectionUtils.collect(infoList, infoIdentityTransformer, ids);
        IdentityQuery identityQuery = new IdentityQuery();
        identityQuery.setLimit(infoQuery.getLimit());
        identityQuery.setCurrentPage(infoQuery.getCurrentPage());
        identityQuery.clear();
        identityQuery.setIds(Arrays.asList(ids.toArray(new Integer[]{})));
        return CommonResult.successReturn(userPersonal(identityQuery, queryInfoStrategyListByRole(infoQuery.getRole())), result.getTotalCount());
    }

    @Override
    public CommonResult<List<UserDescVO>> queryByOutSchool(IdentityQuery identityQuery) {
        //查找北京上海杭州的成员
        List<Info> outSchoolStu = infoBO.queryByInfoStrategy(Arrays.<InfoStrategy>asList(new BasicInfoStrategy(InfoType.Basic, IKEY.ADDRESS, Address.beijing.name()), new BasicInfoStrategy(InfoType.Basic, IKEY.ADDRESS, Address.shanghai.name()), new BasicInfoStrategy(InfoType.Basic, IKEY.ADDRESS, Address.hangzhou.name())));
        List<Integer> ids = new ArrayList<>(outSchoolStu.size());
        CollectionUtils.collect(outSchoolStu, infoIdentityTransformer, ids);
        identityQuery.setIds(ids);
        //查找所有的用户信息
        List<UserDescVO> userDescVOList = supplementIssueAndChild(userPersonal(identityQuery));
        Info info = new Info();
        info.setType(InfoType.Basic.name());
        info.setKey(IKEY.ADDRESS);
        Collections.sort(userDescVOList, new InfoComparator(info));
        return CommonResult.successReturn(userDescVOList);
    }

    @Override
    public CommonResult<List<UserDescVO>> queryOrByGrade(TopicPhaseAble able, IdentityQuery identityQuery, boolean is) {
        List<Info> infoList = infoBO.queryByInfoStrategy(Collections.<InfoStrategy>singletonList(new BasicInfoStrategy(InfoType.GRADE, TopicPhase.openGrade_one.name(), null)));
        if (is) {
            identityQuery.setIds(findTopicPhaseAbleInfo(able, infoList));
        } else {
            identityQuery.setNotIds(findTopicPhaseAbleInfo(able, infoList));
        }
        //如果必须要填充issue 则不需要使用supplementIssueAndChild
        List<UserDescVO> userDescVOList = supplementIssueAndChild(userPersonal(identityQuery));
        return CommonResult.successReturn(userDescVOList, identityQuery.getCount().intValue());
    }

    private List<Integer> findTopicPhaseAbleInfo(TopicPhaseAble able, List<Info> infoList) {
        List<Info> resultList = new ArrayList<>();
        CollectionUtils.select(infoList, InfoKeyPredicate.create(InfoType.GRADE, able), resultList);
        List<Integer> ids = new ArrayList<>(resultList.size());
        CollectionUtils.collect(resultList, infoIdentityTransformer, ids);
        return ids;
    }

    private List<UserDescVO> supplementIssueAndChild(List<UserDescVO> userDescVOList) {
        Set<Integer> ids = new HashSet<>();
        CollectionUtils.collect(userDescVOList, new Transformer() {
            @Override
            public Object transform(Object o) {
                UserDescVO userDescVO = (UserDescVO) o;
                Info info = new Info();
                info.setType(InfoType.TOPIC.name());
                info.setKey(IKEY.TopicId);
                String id = InfoUtils.getInfoValue(userDescVO.getInfoList(), info);
                return id == null ? 0 : Integer.parseInt(id);
            }
        }, ids);
        IssueQuery issueQuery = new IssueQuery();
        issueQuery.clear();
        issueQuery.setIds(new ArrayList<Integer>(ids));
        issueQuery.setIssuePhaseList(IKEY.statusSet);
        List<Issue> issueList = issueBO.findByQueryWith(issueQuery).getData();
        Map<Integer, Issue> issueMap = Utils.modelListToMapOfId(issueList);
        Info info = new Info();
        info.setType(InfoType.TOPIC.name());
        for (UserDescVO userDescVO : userDescVOList) {
            info.setKey(IKEY.TopicId);
            String id = InfoUtils.getInfoValue(userDescVO.getInfoList(), info);
            if (id == null) {
                continue;
            }
            Issue issue = issueMap.get(Integer.parseInt(id));
            userDescVO.setIssue(issue);
            info.setKey(IKEY.TopicName);
            id = InfoUtils.getInfoValue(userDescVO.getInfoList(), info);
            if (id == null) {
                continue;
            }
            //转换并清空
            IssueContent issueContent = JSONObject.parseObject(issue.getContent(), IssueContent.class);
            for (Task task : issueContent.getTaskList()) {
                if (id.equals(task.getNid())) {
                    userDescVO.setTask(task);
                    break;
                }
            }
        }
        return userDescVOList;
    }

    private List<InfoStrategy> queryInfoStrategyListByRole(Role role) {
        if (Role.stu == role) {
            return IKEY.StuInfoAll;
        } else if (Role.tea == role) {
            return IKEY.teaInfoStrategyList;
        } else {
            return null;
        }
    }

    @Override
    public CommonResult<List<UserDescVO>> queryByTwoOpenGrade(IdentityQuery identityQuery) {
        Example gradeExample = new Example();
        gradeExample.createCriteria().andEqualTo("`key`", "openGrade").andEqualTo("`value`", "NO").andEqualTo("del", "0");
        List<Info> openGradeList = infoDAO.selectByExample(gradeExample);
        Example infoOpenGrade = new Example();
        infoOpenGrade.createCriteria().andEqualTo("`key`", GradeTimeType.OPEN_GRADE_TWO.getKey()).andEqualTo("del", "0");
        List<Info> openInfoList = infoDAO.selectByExample(infoOpenGrade);

        List<Integer> ids = checkTwoOpenGrade(openGradeList, openInfoList);
        identityQuery.setIds(ids);
        List<UserDescVO> userPersonal = userPersonal(identityQuery); // 这个是查询用户的详细信息的 这是最后结果查询出来然后在搞的吧
        Info info = new Info();
        info.setType(InfoType.Tea.name());
        info.setKey(IKEY.Guide);
        //这个是排序
        Collections.sort(userPersonal, new InfoComparator(info));
        return CommonResult.successReturn(userPersonal);
    }

    @Override
    public CommonResult<List<UserDescVO>> getOpenGradeNull(IdentityQuery identityQuery) {
        Example openExample = new Example();
        openExample.createCriteria().andEqualTo("`key`", IKEY.OPEN_GRADE).andEqualTo("del","0");
        List<Info> openGradeResult = infoDAO.selectByExample(openExample);

        Example identityExample = new Example();
        identityExample.createCriteria().andEqualTo("`role`", "stu").andEqualTo("del","0");
        List<Identity> identityResult =  identityDAO.selectByExample(identityExample);

        List<UserDescVO> userPersonal = null;
        List<Integer> ids = checkNullOpenGrade(openGradeResult, identityResult);
        if(CollectionUtils.isEmpty(ids)){
            userPersonal = Lists.newArrayList();
        }else {
            identityQuery.setIds(ids);
            userPersonal = userPersonal(identityQuery); // 这个是查询用户的详细信息的 这是最后结果查询出来然后在搞的吧
        }
        Info info = new Info();
        info.setType(InfoType.Tea.name());
        info.setKey(IKEY.Guide);
        //这个是排序
        Collections.sort(userPersonal, new InfoComparator(info));
        return CommonResult.successReturn(userPersonal);
    }

    public UserDescVO getUserDesc(Integer id) {
        UserDescVO userDescVO = CachePool.userDescVOCacheMap.get(id);
        if (userDescVO != null) {
            return userDescVO;
        }
        userDescVO = new UserDescVO();
        Identity identity = identityDAO.selectByPrimaryKey(id);
        if (identity == null) {
            return null;
        }
        userDescVO.setIdentity(identity);
        List<Info> infoList = infoBO.queryByUser(id);
        userDescVO.setInfoList(infoList);
        Issue issue = null;
        String nid = null;
        for (Info info : infoList) {
            if (InfoType.TOPIC.name().equals(info.getType())) {
                if ("topicId".equals(info.getKey())) {
                    issue = new Issue();
                    issue.setId(Integer.parseInt(info.getValue()));
                    continue;
                }
                if ("childTopicId".equals(info.getKey())) {
                    nid = info.getValue();
                }
            }
        }
        if (issue != null) {
            issue = issueBO.get(issue.getId());
            if (issue != null && nid != null) {
                userDescVO.setIssue(issue);
                for (Task tk : JSONObject.parseObject(issue.getContent(), IssueContent.class).getTaskList()) {
                    if (nid.equals(tk.getNid())) {
                        userDescVO.setTask(tk);
                        break;
                    }
                }
            }
        }
        CachePool.userDescVOCacheMap.put(id, userDescVO);
        return userDescVO;
    }

    //校内开题学生
    @Override
    public CommonResult<List<UserDescVO>> queryBySchool(IdentityQuery identityQuery) {
        //查找开题在校学生
        List<Info> schoolStu = infoBO.queryByInfoStrategy(Arrays.<InfoStrategy>asList(new BasicInfoStrategy(InfoType.Basic, IKEY.ADDRESS, Address.zhengzhou.name())));
        List<Integer> ids = new ArrayList<>(schoolStu.size());
        CollectionUtils.collect(schoolStu, infoIdentityTransformer, ids);
        identityQuery.setIds(ids);
        //查找所有的用户信息
        List<UserDescVO> userPersonal = userPersonal(identityQuery); // 这个是查询用户的详细信息的 这是最后结果查询出来然后在搞的吧
        //List<UserDescVO> userDescVOList = supplementIssueAndChild(userPersonal(identityQuery));
        Info info = new Info();
        info.setType(InfoType.Tea.name());
        info.setKey(IKEY.Guide);
        //这个是排序
        Collections.sort(userPersonal, new InfoComparator(info));
        return CommonResult.successReturn(userPersonal);


    }

    @Override
    public CommonResult<List<Identity>> queryAllTea(IdentityQuery identityQuery) {
        //检索教师
        identityQuery.setRole(Role.tea);
        Criteria criteria = getCriteria(identityQuery);
        Example example = Example.createOfPage(identityQuery);
        example.or(criteria);
        List<Identity> list = identityDAO.selectByExample(example);
        if (list.size() < identityQuery.getPageSize()) {
            return CommonResult.successReturn(list);
        } else {
            example.cleanPage();
            int count = identityDAO.countByExample(example);
            identityQuery.setCount((long) count);
            return CommonResult.successReturn(list, count);
        }
    }

    /**
     * <p>功能描述：根据未通过学生列表 和 二次标识学生列表 去重获得学生ID List</p>
     * <p>创建人：yangxiaotian</p>
     * <p>创建日期：2017-05-18 20:09:49</p>
     *
     * @param openGradeNo
     * @param openGradeTwo
     * @return
     */
    private List<Integer> checkTwoOpenGrade(List<Info> openGradeNo, List<Info> openGradeTwo) {
        List<Integer> result = Lists.newArrayList();

        Set<Integer> openGradeList = Sets.newHashSet();
        if (!CollectionUtils.isEmpty(openGradeNo)) {
            for (Info infoNo : openGradeNo) {
                openGradeList.add(infoNo.getIdentityId());
            }
        }
        if (!CollectionUtils.isEmpty(openGradeTwo)) {
            for (Info infoTwo : openGradeTwo) {
                openGradeList.add(infoTwo.getIdentityId());
            }
        }
        result.addAll(openGradeList);
        return result;
    }

    /**
     * <p>功能描述:获取没有开题成绩的学生 取差集</p>
     * <p>创建人：yangxiaotian</p>
     * <p>创建日期：2017-05-18 21:49:45</p>
     *
     * @param openGrade
     * @param stu
     * @return
     */
    private List<Integer> checkNullOpenGrade(List<Info> openGrade, List<Identity> stu){
        List<Integer> open = Lists.newArrayList();
        List<Integer> result = Lists.newArrayList();
        if (!CollectionUtils.isEmpty(openGrade)){
            for (Info  info : openGrade){
                open.add(info.getIdentityId());
            }
        }
        if (!CollectionUtils.isEmpty(stu)){
            for (Identity idntity : stu){
                result.add(idntity.getId());
            }
        }
        result.removeAll(open);
        return result;
    }
}